package org.example;

import javax.swing.*;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

/**
 * idea.t_users 表中有2千万行大批量数据,总数据大小1032mb
 * -Xmx800m  采用流式读取的方式,不会发生oom
 */
public class AppJdbcFetchSize {
    public static void main(String[] args) throws Exception {
        System.out.println("-----------AppJdbcFetchSize类main方法执行了-------------");

        String jdbcUrl = "jdbc:mysql://localhost:3306/idea?useCursorFetch=true&useSSL=false&serverTimezone=UTC";
        String username = "root";
        String password = "scyy";

        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;

        try {
            Class.forName("com.mysql.jdbc.Driver");

            // 建立连接
            conn = DriverManager.getConnection(jdbcUrl, username, password);

            // 创建 PreparedStatement（关键参数）
            ps = conn.prepareStatement(
                    "select  id,name,gender,age  from t_users;"
                    ,ResultSet.TYPE_FORWARD_ONLY,
                    ResultSet.CONCUR_READ_ONLY
            );

            // 关键：告诉 MySQL 使用“流式结果集”，不要预加载所有数据
            ps.setFetchSize(Integer.MIN_VALUE);

            // 执行查询
            long start = System.currentTimeMillis();
            System.out.println("获取结果集----11");
            rs = ps.executeQuery();
            System.out.println("获取结果集----22");
            long end = System.currentTimeMillis();
            System.out.println("获取结果集耗时:" + (end - start) );

            int count = 0;
            // 逐行处理结果（低内存占用）
            while (rs.next()) {
                count++;
                if (count % 100000 == 0) {
                    int id = rs.getInt("id");
                    String name = rs.getString("name");
                    System.out.println("ID: " + id + ", name: " + name);
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 关闭资源
            try {
                if (rs != null) rs.close();
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
            try {
                if (ps != null) ps.close();
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
            try {
                if (conn != null) conn.close();
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
    }
}